home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Windows 95 Programs / Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso / 0769 / netwrkm.c < prev    next >
C/C++ Source or Header  |  1997-04-10  |  9KB  |  294 lines

  1. //
  2. // Finger Version 3.1, a Windows Sockets Finger Client
  3. //
  4. // Copyright 1992, 1993 Network Research Corporation
  5. //
  6. // Permission to use, modify, and distribute this software and its
  7. // documentation for any purpose and without fee is hereby granted, provided
  8. // that the above copyright notice appears in all copies and that both
  9. // that copyright notice and this permission notice appear in supporting
  10. // documentation.  NRC makes no claims as to the suitability of this software
  11. // for any purpose.
  12. //
  13. // Module NETWRKM uses Windows Sockets asynchronous (message based) calls to
  14. // query a remote finger server for a list of currently logged in users.
  15. // Module FINGER initiates the operation by calling FingerStart(), and
  16. // NETWRKM signals completion by calling FingerFinish(). NETWRKM uses DSPLIST
  17. // functions to send the retrieved data to the FINGER user interface module.
  18. //
  19. // 04/01/92 Lee Murach  Created.
  20. // 11/30/92 Lee Murach  Adapted for WS 1.1 WSAAsyncSelect()
  21. // 12/02/92 Lee Murach  Restructured for Finger 3.0 integrated release
  22. // 01/15/92 Lee Murach  Change FD_READ to FD_READ | FD_CLOSE
  23. // 03/01/93 Lee Murach  Added WSAEWOULDBLOCK check to DoConnect()
  24. // 03/25/93 Lee Murach  Added per-user finger support.
  25. //
  26.  
  27. #include <memory.h>
  28. #include <string.h>
  29. #include <windows.h>
  30. #include <winsock.h>
  31. #include "finger.h"
  32.  
  33. // messages for windows sockets returns
  34. #define WM_SERVICE            (WM_USER + 1)
  35. #define WM_HOSTRESOLVED       (WM_USER + 2)
  36. #define WM_CONNECTED          (WM_USER + 3)
  37. #define WM_OKTORECV           (WM_USER + 4)
  38. #define NETWINDOW "NetWindow"
  39.  
  40. LONG FAR APIENTRY NetWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  41. LONG DoResolveHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  42. LONG DoConnect(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  43. LONG DoQuery(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  44. LONG DoRetrieval(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  45. void LoadEntBuf(IPA ipa);
  46.  
  47. DECODEWORD netMsgs[] =                 // network window messages & handlers
  48. {
  49.    WM_SERVICE,       DoResolveHost,
  50.    WM_HOSTRESOLVED,  DoConnect,
  51.    WM_CONNECTED,     DoQuery,
  52.    WM_OKTORECV,      DoRetrieval
  53. };
  54.  
  55. SOCKET   Sock;                         // connects to remote server's socket
  56. int      Port;                         // hold port for finger service
  57. char     EntBuf[MAXGETHOSTSTRUCT];     // buf for service & resolve returns
  58. HWND     hNetWnd;                      // network window handle
  59.  
  60. //
  61. // InitNetApp -- registers window class for the network module's invisible
  62. // child window. This is called only for the first instance of finger.
  63. //
  64. VOID InitNetApp(VOID)
  65. {
  66.    WNDCLASS wndclass;
  67.  
  68.    wndclass.style         = 0;
  69.    wndclass.lpfnWndProc   = NetWndProc;
  70.    wndclass.cbClsExtra    = 0;
  71.    wndclass.cbWndExtra    = 0;
  72.    wndclass.hInstance     = hInst;
  73.    wndclass.hIcon         = 0;
  74.    wndclass.hCursor       = 0;
  75.    wndclass.hbrBackground = 0;
  76.    wndclass.lpszMenuName  = NULL;
  77.    wndclass.lpszClassName = NETWINDOW;
  78.  
  79.    RegisterClass(&wndclass);
  80. }
  81.  
  82. //
  83. // InitNetInst -- initializes the network module by creating an invisible
  84. // child of the main finger window which will be used to receive Windows
  85. // Sockets notification messages.  The window will be automatically
  86. // destroyed when the main window exits, so no finalization is required.
  87. //
  88. VOID InitNetInst(HWND hWnd)
  89. {
  90.    hNetWnd = CreateWindow( NETWINDOW, "", WS_OVERLAPPEDWINDOW,
  91.                            CW_USEDEFAULT, CW_USEDEFAULT,
  92.                            CW_USEDEFAULT, CW_USEDEFAULT,
  93.                            hWnd, 0, hInst, NULL);
  94. }
  95.  
  96. //
  97. // NetWndProc -- callback function for network window.  The network window
  98. // is a child window created especially to receive windows sockets network
  99. // messages.  The function decodes and routes to appropriate message handler.
  100. //
  101. LONG FAR APIENTRY NetWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  102. {
  103.    int i;
  104.  
  105.    for (i = 0; i < dim(netMsgs); i++)
  106.    {
  107.       if (wMsg == netMsgs[i].Code)
  108.          return((*netMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam));
  109.    }
  110.  
  111.    return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  112. }
  113.  
  114. //
  115. // FingerStart -- called by FINGER module to initiate a conversation with
  116. // the remote finger server.  We start by resolving the finger tcp service
  117. // to a port number. Windows Sockets WSAAsync routines signal completion
  118. // by posting messages, which are dispatched to appropriate handlers.
  119. //
  120. VOID FingerStart(VOID)
  121. {
  122.    if (WSAAsyncGetServByName(hNetWnd, WM_SERVICE, "finger", "tcp",
  123.                              EntBuf, sizeof(EntBuf)) == -1)
  124.    {
  125.       ReportFingerErr(FE_NOPORT);
  126.       FingerFinish(FE_ERROR);
  127.    }
  128. }
  129.  
  130. //
  131. // DoResolveHost -- resolves host specifier to an IP address.  Since we
  132. // allow a "dotted decimal" IP address to be entered in lieu of a DNS host
  133. // name, we check for this syntax before assuming a DNS name.
  134. //
  135. LONG DoResolveHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  136. {
  137.    IPA ipa;
  138.  
  139.    if (WSAGETSELECTERROR(lParam))
  140.    {
  141.       ReportFingerErr(FE_NOPORT);         // cannot locate finger service
  142.       FingerFinish(FE_ERROR);
  143.       return(FALSE);
  144.    }
  145.  
  146.    Port = ((SERVENT *)EntBuf)->s_port;    // we're going to reuse the buffer
  147.  
  148.    // if host specifier is dotted decimal ip address, resolve right here
  149.    if ((ipa = INET_ADDR(szHostName)) != INADDR_NONE)
  150.    {
  151.       LoadEntBuf(ipa);
  152.       PostMessage(hNetWnd, WM_HOSTRESOLVED, 0, 0);
  153.       return(FALSE);
  154.    }
  155.  
  156.    // assume specifier is DNS host name
  157.    if (WSAAsyncGetHostByName(hNetWnd, WM_HOSTRESOLVED, szHostName,
  158.                              EntBuf, sizeof(EntBuf)) == -1)
  159.    {
  160.       ReportFingerErr(FE_NOHOST);
  161.       FingerFinish(FE_ERROR);
  162.    }
  163.  
  164.    return(FALSE);
  165. }
  166.  
  167. //
  168. // LoadEntBuf -- loads the EntBuf (sufficiently) with a HOSTENT and
  169. // referenced IPA.  This is so we can return IPAs in the same
  170. // manner as a WSAAsync call.
  171. //
  172. void LoadEntBuf(IPA ipa)
  173. {
  174.    LPHOSTENT phe = (LPHOSTENT) EntBuf;
  175.    LPPIPA ppipa = (LPPIPA) (EntBuf + sizeof(HOSTENT));
  176.    LPIPA pipa = (LPIPA) (EntBuf + sizeof(HOSTENT) + sizeof(LPPIPA));
  177.  
  178.    _fmemset(phe, 0, sizeof(HOSTENT));
  179.    phe->h_addr_list = (char FAR * FAR *) ppipa;
  180.    *ppipa = pipa;
  181.    *pipa = ipa;
  182. }
  183.  
  184. //
  185. // DoConnect -- allocates a socket and connects to remote finger server.
  186. //
  187. LONG DoConnect(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  188. {
  189.    if (WSAGETSELECTERROR(lParam))
  190.    {
  191.       ReportFingerErr(FE_NOHOST);       // could not resolve host name
  192.       FingerFinish(FE_ERROR);
  193.       return(FALSE);
  194.    }
  195.  
  196.    if ((Sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0)
  197.    {
  198.       SOCKADDR_IN server;
  199.       u_long block = FALSE;
  200.       HOSTENT *phe = (HOSTENT *) EntBuf;
  201.  
  202.       memset(&server, 0, sizeof(server));
  203.       server.sin_family = AF_INET;
  204.       server.sin_port = Port;
  205.       server.sin_addr = *((IN_ADDR FAR *) *phe->h_addr_list);
  206.  
  207.       // post message when connect is established
  208.       WSAAsyncSelect(Sock, hNetWnd, WM_CONNECTED, FD_CONNECT);
  209.  
  210.       if (  connect(Sock, (SOCKADDR *)&server, sizeof(server)) < 0 &&
  211.             WSAGetLastError() != WSAEWOULDBLOCK)
  212.       {
  213.          ReportFingerErr(FE_NOCONN);
  214.          FingerFinish(FE_ERROR);
  215.       }
  216.    }
  217.    else
  218.    {
  219.       ReportFingerErr(FE_NOSOCK);
  220.       FingerFinish(FE_ERROR);
  221.    }
  222.  
  223.    return(FALSE);
  224. }
  225.  
  226. //
  227. // DoQuery -- sends a query for all currently logged in users to remote
  228. // server.
  229. //
  230. LONG DoQuery(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  231. {
  232.    char msg[MAXUSER+3];
  233.    int msglen;
  234.  
  235.    if (WSAGETSELECTERROR(lParam))
  236.    {
  237.       ReportFingerErr(FE_NOCONN);       // could not connect to server
  238.       FingerFinish(FE_ERROR);
  239.       return(FALSE);
  240.    }
  241.  
  242.    // post message when data is available for read
  243.    WSAAsyncSelect(Sock, hNetWnd, WM_OKTORECV, FD_READ | FD_CLOSE);
  244.  
  245.    strcpy(msg, szUser);
  246.    strcat(msg, "\r\n");
  247.    msglen = strlen(msg);
  248.  
  249.    if (send(Sock, msg, msglen, 0) != msglen)
  250.    {
  251.       ReportFingerErr(FE_NOSEND);
  252.       FingerFinish(FE_ERROR);
  253.       return(FALSE);
  254.    }
  255.    
  256.    OpenDisplayList();   // new display list will contain received data
  257.    
  258.    return(FALSE);
  259. }
  260.  
  261. //
  262. // DoRetrieval -- fetches ascii text from remote finger server, and builds
  263. // display list until the end of the text stream.
  264. //
  265. LONG DoRetrieval(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  266. {
  267.    static char buf[500];
  268.    int nchars, err = 0;
  269.  
  270.    /* receives data not to exceed buf size & reenables notification
  271.       of more data pending */
  272.  
  273.    if ((nchars = recv(Sock, (char FAR *)&buf, sizeof(buf), 0)) > 0)
  274.    {
  275.       PushChars(buf, nchars);        // adds character to display list
  276.       return(FALSE);
  277.    }
  278.  
  279.    CloseDisplayList();               // close list if error or end-of-data
  280.    closesocket(Sock);                // don't need socket anymore
  281.  
  282.    if (nchars < 0)
  283.    {
  284.       FreeDisplayList();
  285.       ReportFingerErr(FE_NORECV);   // error during receive
  286.       err = FE_ERROR;
  287.    }
  288.  
  289.    FingerFinish(err);               // signal end-of-finger
  290.  
  291.    return(FALSE);
  292. }
  293.  
  294.